﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using AnthStat;

namespace NutriStat.Statistics
{
    public abstract class GrowthReferenceBase : IGrowthReference
    {
        #region Private Data
        private string name;
        private string fullName;
        #endregion Private Data

        #region Public Data
        internal int BMIUpper;
        internal int BMILower;
        internal int WeightHeightUpper;
        internal int WeightHeightLower;
        internal int WeightLengthUpper;
        internal int WeightLengthLower;
        internal int WeightHeightAgeLower;
        internal int WeightHeightAgeUpper;
        internal int WeightLengthAgeLower;
        internal int WeightLengthAgeUpper;
        internal int WeightAgeUpper;
        internal int WeightAgeLower;
        internal int HeightAgeUpper;
        internal int HeightAgeLower;
        internal int LengthAgeUpper;
        internal int LengthAgeLower;
        internal int SSFUpper;
        internal int SSFLower;
        internal int TSFUpper;
        internal int TSFLower;
        internal int HeadUpper;
        internal int HeadLower;
        internal int MUACUpper;
        internal int MUACLower;
        #endregion Public Data

        public GrowthReferenceBase()
        {
            // CDC Numbers
            HeightAgeLower = 24;
            HeightAgeUpper = 239;
            LengthAgeLower = 0;
            LengthAgeUpper = 36;

            WeightHeightLower = 77;
            WeightHeightUpper = 121;
            WeightLengthLower = 45;
            WeightLengthUpper = 103;

            WeightHeightAgeLower = 0;
            WeightHeightAgeUpper = 244;
            WeightLengthAgeLower = 0;
            WeightLengthAgeUpper = 244;

            WeightAgeLower = 0;
            WeightAgeUpper = 239;

            HeadLower = 0;
            HeadUpper = 36;

            BMILower = 24;
            BMIUpper = 239;

            // WHO Numbers
            SSFLower = 3;
            SSFUpper = 59;

            TSFLower = 3;
            TSFUpper = 59;
        }

        public virtual string GetZForBMI(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {            
            if (age >= BMILower && age <= BMIUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 0);            
            else
                return NutriStringConstants.Null;
        }

        public virtual string GetZForWeightHeight(ref double z, ref double p, ref double flag, double rawScore, double age, double height, short gender, bool recumbent)
        {
            if (recumbent)
            {
                if (height >= WeightLengthLower && height <= WeightLengthUpper
                    &&
                    age >= WeightLengthAgeLower && age <= WeightLengthAgeUpper)
                    return GetZ(ref z, ref p, ref flag, rawScore, height, gender, 6);
                else
                    return NutriStringConstants.Null;
            }
            else
            {
                if (height >= WeightHeightLower && height <= WeightHeightUpper
                    &&
                    age >= WeightHeightAgeLower && age <= WeightHeightAgeUpper)                  
                    return GetZ(ref z, ref p, ref flag, rawScore, height, gender, 5);                
                else
                    return NutriStringConstants.Null;
            }
        }

        public virtual string GetZForWeightAge(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {
            if (age >= WeightAgeLower && age <= WeightAgeUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 4);
            else
                return NutriStringConstants.Null;
        }

        public virtual string GetZForHeightAge(ref double z, ref double p, ref double flag, double rawScore, double age, short gender, bool recumbent)
        {
            if (this is WHO1978GrowthReference)
            {
                if (age >= LengthAgeLower && age <= LengthAgeUpper)
                    return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 3);
                else if (age >= HeightAgeLower && age <= HeightAgeUpper)
                    return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 2);
                else
                    return NutriStringConstants.Null;
            }
            else
            {
                if (recumbent)
                {
                    if (age >= LengthAgeLower && age <= LengthAgeUpper)
                        return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 3);
                    else
                        return NutriStringConstants.Null;
                }
                else
                {
                    if (age >= HeightAgeLower && age <= HeightAgeUpper)
                        return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 2);
                    else
                        return NutriStringConstants.Null;
                }
            }
        }

        public virtual string GetZForSSF(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {
            if (age >= SSFLower && age <= SSFUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 7);
            else
                return NutriStringConstants.Null;
        }

        public virtual string GetZForTSF(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {
            if (age >= SSFLower && age <= SSFUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 8);
            else
                return NutriStringConstants.Null;
        }

        public virtual string GetZForHead(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {
            if (age >= HeadLower && age <= HeadUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 1);
            else
                return NutriStringConstants.Null;
        }

        public virtual string GetZForMUAC(ref double z, ref double p, ref double flag, double rawScore, double age, short gender)
        {
            if (age >= MUACLower && age <= MUACUpper)
                return GetZ(ref z, ref p, ref flag, rawScore, age, gender, 0);
            else
                return NutriStringConstants.Null;
        }

        protected static bool CheckFlagForNull(double value)
        {
            if (value < -900 || value > 900)
                return true;
            else
                return false;
        }

        public abstract string GetPercentOfMedianForWeightHeight(double rawScore);
        public abstract string GetPercentOfMedianForWeightAge(double rawScore);
        public abstract string GetPercentOfMedianForHeightAge(double rawScore);

        protected virtual string GetZ(ref double z, ref double p, ref double flag, double rawScore, double age, short gender, short type)
        {
            double Z = 0;
            double P = 0;
            try
            {
                if (this is WHO1978GrowthReference)
                    Z = AnthStat.NutriDataCalc.GetZScoreNCHS(rawScore, age, gender, type, ref flag); 
                else
                    Z = AnthStat.NutriDataCalc.GetZScore(rawScore, age, gender, type, this.Name, ref flag);                
                P = AnthStat.NutriDataCalc.GetPercentile(Z);
                z = Z;
                p = P;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            //if (this.Name == "WHO2006" && type == 5)
            //    MessageBox.Show(this.Name + " 2   " + Z.ToString());

            return Z.ToString();
        }

        public List<string> ColumnNames;

        /// <summary>
        /// Gets/sets the reference's short name.
        /// </summary>
        public string Name 
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        /// <summary>
        /// Gets/sets the reference's full name.
        /// </summary>
        public string FullName
        {
            get
            {
                return fullName;
            }
            set
            {
                fullName = value;
            }
        }
    }
}
